/*
 * @Description: 自定义primitive光锥，entity底座
 * @Author: your name
 * @Date: 2024-09-09 20:55:47
 * @version:
 * @LastEditors: 杨帆 14613505+yang-fan-yf123@user.noreply.gitee.com
 * @LastEditTime: 2024-09-14 10:56:44
 */
import ConeGlowBottomCircleMaterialProperty from './ConeGlowBottomCircleMaterialProperty';
import WallGradientsMaterialProperty from './WallGradientsMaterialProperty';
import SimpleLabel from '../Bubble/htmlMarker';
import getCesiumHeat from './cesiumHeatMap';
import * as Cesium from 'cesium';
// 光锥
export const coneWithLight = (viewer, options) => {
  const position = Cesium.defaultValue(
    options.position,
    Cesium.Cartesian3.ZERO
  );
  const height = Cesium.defaultValue(options.height, 700);
  const bottomRadius = Cesium.defaultValue(options.bottomRadius, 100);
  const color = Cesium.defaultValue(options.color, Cesium.Color.AQUA);
  const modelMatrix = Cesium.Matrix4.multiplyByTranslation(
    Cesium.Transforms.eastNorthUpToFixedFrame(position),
    new Cesium.Cartesian3(0.0, 0.0, height * 0.5),
    new Cesium.Matrix4()
  );

  const cylinderGeometry = new Cesium.CylinderGeometry({
    length: height,
    topRadius: 0.0,
    bottomRadius: bottomRadius * 0.7,
    vertexFormat:
      Cesium.MaterialAppearance.MaterialSupport.TEXTURED.vertexFormat,
  });

  const cone = new Cesium.GeometryInstance({
    geometry: cylinderGeometry,
    modelMatrix: modelMatrix,
  });

  return viewer.scene.primitives.add(
    new Cesium.Primitive({
      geometryInstances: [cone],
      appearance: new Cesium.MaterialAppearance({
        material: new Cesium.Material({
          fabric: {
            type: 'VtxfShader1',
            uniforms: {
              color: color,
            },
            source: /*glsl*/ `
                            uniform vec4 color;
                            czm_material czm_getMaterial(czm_materialInput materialInput)
                            {
                                czm_material material = czm_getDefaultMaterial(materialInput);
                                vec2 st = materialInput.st;
                                float time=fract(czm_frameNumber/10.0);
                                float isAlpha=step(0.5,time);
                                float dis = distance(st, vec2(0.5));
                                material.diffuse =1.9 * color.rgb;
                                if(isAlpha>=1.0){
                                    material.alpha = color.a * dis *2.0;
                                }else{
                                    material.alpha = color.a * dis *1.5;
                                }

                                return material;
                            }
                        `,
          },
          translucent: false,
        }),
        faceForward: false, // 当绘制的三角面片法向不能朝向视点时，自动翻转法向，从而避免法向计算后发黑等问题
        closed: true, // 是否为封闭体，实际上执行的是是否进行背面裁剪
      }),
    })
  );
};
// 站点底部圆环
export const bottomCircle = (viewer, options) => {
  const position = Cesium.defaultValue(
    options.position,
    Cesium.Cartesian3.ZERO
  );
  const color = Cesium.defaultValue(options.color, Cesium.Color.AQUA);
  const bottomRadius = Cesium.defaultValue(options.bottomRadius, 100);
  return viewer.entities.add({
    position: position,
    ellipse: {
      semiMinorAxis: bottomRadius * 2,
      semiMajorAxis: bottomRadius * 2,
      height: 0.0,
      material: new ConeGlowBottomCircleMaterialProperty(color),
    },
  });
};

// 渲染站点  传入颜色十六进制字符串，名称，位置{lng,lat,height}
const stations = [];
export const renderStation = (viewer, options) => {
  const position = Cesium.defaultValue(options.positions, {
    lng: 0,
    lat: 0,
  });
  const positionCar3 = Cesium.Cartesian3.fromDegrees(
    position.lng,
    position.lat
  );
  const conePrimitve = coneWithLight(viewer, {
    position: positionCar3,
    height: 700,
    bottomRadius: 100,
    color: Cesium.Color.fromCssColorString(options.color),
  });

  const bottomCircleEntity = bottomCircle(viewer, {
    position: positionCar3,
    bottomRadius: 100,
    color: Cesium.Color.fromCssColorString(options.color),
  });
  const target = {
    conePrimitve,
    bottomCircleEntity,
    name: options.name,
  };
  stations.push(target);
  return target;
};

// 删除单个站点，直接删除，而不是隐藏
export const removeStationByName = (viewer, name) => {
  const target = stations.find((item) => item.name === name);
  if (target) {
    const { conePrimitve, bottomCircleEntity } = target;
    viewer.scene.primitives.remove(conePrimitve);
    viewer.entities.remove(bottomCircleEntity);
    stations.splice(stations.indexOf(target), 1);
  }
};

// 删除所有站点
export const removeAllStations = (viewer) => {
  stations.forEach((item) => {
    const { conePrimitve, bottomCircleEntity } = item;
    viewer.scene.primitives.remove(conePrimitve);
    viewer.entities.remove(bottomCircleEntity);
  });
  stations.length = 0;
};

// 通过名称Array控制站点显示隐藏
export const hideStationByName = (names, isShow) => {
  const targets = stations.filter((item) => names.indexOf(item.name) > -1);
  if (targets.length) {
    targets.forEach((target) => {
      const { conePrimitve, bottomCircleEntity } = target;
      conePrimitve.show = isShow;
      bottomCircleEntity.show = isShow;
    });
  }
};

// 创建地铁线路 positions:[{lng,lat,height}]
// color:十六进制颜色字符串
// name:线路名称
const lines = [];
export const renderLines = (viewer, options) => {
  const positions = Cesium.defaultValue(options.positions, [
    {
      lng: 0,
      lat: 0,
    },
  ]);
  const color = Cesium.defaultValue(options.color, Cesium.Color.AQUA);
  const name = Cesium.defaultValue(options.name, 'line');
  const positionRes = Cesium.Cartesian3.fromDegreesArray(positions);
  const lineEnt = viewer.entities.add({
    name,
    polyline: {
      positions: positionRes,
      width: 20,
      //使用cesium默认的泛光线
      material: new Cesium.PolylineGlowMaterialProperty({
        color: color,
        glowPower: 0.12,
      }),
    },
  });
  lines.push(lineEnt);
  return lineEnt;
};

// 删除地铁线路，不是隐藏
export const removeAllLines = (viewer) => {
  lines.forEach((line) => {
    line && viewer.entities.remove(line);
  });
};

// 通过名称控制线路显示隐藏
export const hideLineByName = (names, isShow) => {
  lines.forEach((line) => {
    if (names.indexOf(line.name) > -1) {
      line.show = isShow;
    }
  });
};

// 通过名称整体控制显示隐藏
export const displayByName = (lineNames, stationNames, isShow) => {
  hideLineByName(lineNames, isShow);
  hideStationByName(stationNames, isShow);
  changeDisplayBillBoard(stationNames, isShow);
};

// 渲染全部
export const renderAll = (viewer, dataSource) => {
  // 渲染道路
  if (dataSource.length) {
    dataSource.forEach((item) => {
      const { paths, name, color, stationsList } = item;
      const position = [];
      paths.forEach((path) => {
        position.push(path.lng, path.lat);
      });
      renderLines(viewer, {
        positions: position,
        color: new Cesium.Color.fromCssColorString(color),
        name,
      });
      // 渲染站点
      stationsList.forEach((station) => {
        const { position, name } = station;
        renderStation(viewer, {
          positions: position,
          name,
          color,
        });
      });
    });
  }
};

// 清除全部
export const removeAll = (viewer) => {
  removeAllLines(viewer);
  removeAllStations(viewer);
};

// const billboards = [];
// // 渲染站点标牌，后期还要添加点击查询功能
// export const renderStationBill =async (viewer, options) => {
//   const position = Cesium.defaultValue(options.position, {
//     lng: 0,
//     lat: 0,
//   });
//   const height = Cesium.defaultValue(options.height, 200);
//   const name = Cesium.defaultValue(options.name, "站点");
//   const show = Cesium.defaultValue(options.show, true);
//   const color = Cesium.defaultValue(options.color, "#ff0000");
//   const attr = Cesium.defaultValue(options.attr, {});
//   const isCache=Cesium.defaultValue(options.isCache,true);
//   const billControler = new SimpleLabel(
//     viewer,
//     {
//       position:Cesium.Cartesian3.fromDegrees(position.lng, position.lat, height),
//       label:name,
//       isShow:show,
//       color:color,
//       scaleByDistance:new Cesium.NearFarScalar(1000, 1, 20000, 0.4),
//       attr:attr,
//       type:'marker'
//     }
//   );
//   await billControler.addLabel();

//   const target = {
//     billControler,
//     billboard:billControler.vmInstance.el,
//     name
//   };
//   isCache && billboards.push(target);
//   return target;
// };

// // 清除所有站点标牌
// export const removeAllBillboards = () => {
//   billboards.forEach((item) => {
//     const { billControler } = item;
//     billControler.removeMarker();
//     billControler.queryPopup && billControler.removeQueryPopup();
//   });
// };

// // 根据名称Array控制站点标牌显示与隐藏
// export const changeDisplayBillBoard = (names, isShow) => {
//   const filterBills = billboards.filter(
//     (item) => names.indexOf(item.billControler.label) > -1
//   );
//   filterBills.forEach((item) => {
//     const { billboard, billControler } = item;
//     billControler.isDisplay = isShow;
//     billboard.style.display = isShow ? "block" : "none";
//   });
// };

// 站点标牌 气泡框内容
let billboards = [];
let billboardEntities = [];
// 渲染站点标牌，后期还要添加点击查询功能
export const renderStationBill = async (viewer, options) => {
  const position = Cesium.defaultValue(options.positions, {
    lng: 0,
    lat: 0,
  });
  const height = Cesium.defaultValue(options.height, 400);
  const name = Cesium.defaultValue(options.name, '站点');
  const show = Cesium.defaultValue(options.show, true);
  const color = Cesium.defaultValue(options.color, '#ff0000');
  const attr = Cesium.defaultValue(options.attr, {});
  const isCache = Cesium.defaultValue(options.isCache, true);
  const offect = Cesium.defaultValue(options.offect, [0, 0]);
  console.log('dsadf', attr);
  const labelOptions = {
    position: Cesium.Cartesian3.fromDegrees(position.lng, position.lat, height),
    label: name,
    isShow: show,
    color: color,
    scaleByDistance: new Cesium.NearFarScalar(1000, 1, 20000, 0.4),
    attr: attr,
    type: 'marker', // 可以根据需要修改
    offset: offect,
    fields: options.fields || [], // 如果有传递 fields
    values: options.values || [], // 如果有传递 values
  };
  const billController = new SimpleLabel(viewer, labelOptions);
  // const billboard = billControler.addLabel()
  billController.addLabel().then((billboard) => {
    const target = {
      billController,
      billboard,
    };

    if (isCache) {
      billboardEntities.push(target);
    } else {
      billboards.push(target);
    }
    return target;
  });
};

// 清除所有站点标牌
export const removeAllBillboards = () => {
  billboards.forEach((item) => {
    const { billControler } = item;
    billControler.removeMarker();
  });
};

// 根据名称Array控制站点标牌显示与隐藏
export const changeDisplayBillBoard = (names, isShow) => {
  const filterBills = billboardEntities.filter(
    (item) => names.indexOf(item.billController.label) > -1
  );
  filterBills.forEach((item) => {
    const { billboard, billController } = item;
    billController.isDisplay = isShow;
    billboard.style.display = isShow ? 'block' : 'none';
  });
};

// 添加重保活动圆柱
// options: {
//   position: {lng,lat,height},
//   height: 1000,
//   baseHeight: 0, // 圆柱底部高度
//   radius: 100, // 圆柱半径
//   color: "#ff0000", // 圆柱颜色
//   name: "活动圆柱" // 圆柱名称
// }
const cones = [];
export const addGradientCone = (viewer, options) => {
  // 圆柱颜色
  const wallColor = Cesium.defaultValue(
    new Cesium.Color.fromCssColorString(options.color),
    Cesium.Color.AQUA
  );
  const name = Cesium.defaultValue(options.name, '');
  // 坐标中心，经纬度
  const center = Cesium.defaultValue(options.position, {
    lng: 0,
    lat: 0,
    height: 0,
  });
  console.log(center);
  const wallHeight = Cesium.defaultValue(options.height, 1000);
  const baseHeight = Cesium.defaultValue(options.baseHeight, 0);
  const radius = Cesium.defaultValue(options.radius, 200);
  const positions = generateCirclePoints([center.lng, center.lat], radius);
  //wall中的坐标需要闭合
  positions.push(positions[0]);
  // 将经纬度转为笛卡尔3
  const wallPositions = Cesium.Cartesian3.fromDegreesArray(positions.flat());
  console.log(wallPositions);
  let minimumHeights = []; //最小高度集合
  let maximumHeights = []; //最大高度集合
  wallPositions.forEach((position) => {
    minimumHeights.push(baseHeight);
    maximumHeights.push(baseHeight + wallHeight);
  });

  const cone = viewer.entities.add({
    name,
    center: new Cesium.Cartesian3.fromDegrees(
      center.lng,
      center.lat,
      baseHeight
    ),
    wall: {
      positions: wallPositions,
      minimumHeights: minimumHeights,
      maximumHeights: maximumHeights,
      material: new WallGradientsMaterialProperty(wallColor),
    },
  });
  cones.push(cone);
};
//获取圆上点的经纬度坐标
const generateCirclePoints = (center, radius) => {
  let points = [];
  for (let i = 0; i < 360; i += 2) {
    points.push(getCirclePoint(center[0], center[1], i, radius));
  }
  return points;
};

const getCirclePoint = (lon, lat, angle, radius) => {
  let dx = radius * Math.sin((angle * Math.PI) / 180.0);
  let dy = radius * Math.cos((angle * Math.PI) / 180.0);
  let ec = 6356725 + ((6378137 - 6356725) * (90.0 - lat)) / 90.0;
  let ed = ec * Math.cos((lat * Math.PI) / 180);
  let newLon = ((dx / ed + (lon * Math.PI) / 180.0) * 180.0) / Math.PI;
  let newLat = ((dy / ec + (lat * Math.PI) / 180.0) * 180.0) / Math.PI;
  return [newLon, newLat];
};
// 删除所有圆柱
export const removeAllCones = (viewer) => {
  cones.forEach((cone) => {
    cone && viewer.entities.remove(cone);
  });
  cones.length = 0;
};

// 根据名称视角跳转到对应线路
export const flyToLine = (viewer, name) => {
  const targetEnt = lines.find((item) => item.name === name);
  if (!targetEnt) {
    return;
  }
  viewer.flyTo(targetEnt);
};

// 根据线路名称闪烁线路
let timerBink;
let lastActiveRoute;
export const binkLineByName = (name) => {
  const targetEnt = lines.find((item) => item.name === name);
  if (!targetEnt) {
    return;
  }
  // 如果选中的是刚刚高亮的，判断是否存在定时器，存在的话，就返回
  if (timerBink && name === lastActiveRoute) {
    return;
  }

  // 如果选中的不是刚刚高亮的，直接清除定时器，然后高亮
  if (name !== lastActiveRoute && timerBink) {
    window.clearInterval(timerBink);
    timerBink = null;
    lastActiveEnt.polyline.material.glowPower = 0.12;
  }

  const originGlowPower = targetEnt.polyline.material.glowPower;

  const timeBreak = 600;
  let binkCount = 6;
  let count = 0;

  timerBink = setInterval(() => {
    if (count >= binkCount) {
      window.clearInterval(timerBink);
      timerBink = null;
    } else {
      let isBink = count % 2 === 0;
      targetEnt.polyline.material.glowPower = isBink
        ? originGlowPower * 4
        : originGlowPower;
      count++;
    }
  }, timeBreak);
};

// 视角飞到圆柱
export const flyToCone = (viewer, name) => {
  const targetCone = cones.find((item) => item.name === name);

  if (!targetCone) {
    return;
  }
  viewer.flyTo(targetCone, {
    offset: new Cesium.HeadingPitchRange(
      Cesium.Math.toRadians(40),
      Cesium.Math.toRadians(-40),
      5000
    ),
  });
};
export const renderHeat = (viewer, dataSource) => {
  const CesiumHeat = getCesiumHeat(Cesium);
  let heat = new CesiumHeat(
    viewer,
    {
      autoMaxMin: true,
      // data list, each has x, y, and value | 数据数组，每个包含 x,y,value字段
      data: dataSource,
    },
    // bbox for heatmap | 只在范围内显示热力图拉近会清晰些，默认整个地球但拉近后巨模糊
    [114.03, 30.2, 114.45, 30.9]
  );

  const destroyHeat = () => {
    heat.destory();
  };
  // 将清除方法暴露出去
  return destroyHeat;
};
// 视角飞到全局
export const flyToDefaultView = (viewer) => {
  viewer.camera.flyTo({
    destination: Cesium.Cartesian3.fromDegrees(113.95, 30.19, 34000),
    duration: 2,
    orientation: {
      heading: Cesium.Math.toRadians(35.0),
      pitch: Cesium.Math.toRadians(-37.0),
      roll: 0.0,
    },
  });
};
// 路径规划，点击站点跳转到对应的站点
export const focusOnStation = (viewer, name, ents = stations) => {
  const target = ents.find((item) => item.name === name);
  if (target) {
    console.log(target);

    viewer.flyTo(target.bottomCircleEntity, {
      duration: 3.0, // 飞行持续时间，单位为秒
      offset: new Cesium.HeadingPitchRange(
        Cesium.Math.toRadians(0.0), // 偏航角度
        Cesium.Math.toRadians(-45.0), // 俯仰角
        2000 // 距离实体的距离
      ),
    });
  }
};
export const removeByCacheData = (viewer, cacheData) => {
  if (Object.keys(cacheData).length === 0) {
    return;
  }
  const { lineEnts, stationEnts, billboards } = cacheData;
  lineEnts.forEach((line) => viewer.entities.remove(line));
  stationEnts.forEach((station) => {
    const { conePrimitive, bottomCircleEntity } = station;
    viewer.scene.primitives.remove(conePrimitive);
    viewer.entities.remove(bottomCircleEntity);
  });
  billboardEntities.forEach((item) => {
    const { billController } = item;
    billController.removeMarker();
    billController.removeQueryPopup();
  });
};
